const _ = require('lodash');
const async = require('async');
const services = require('../../services');

const commonService = services.common;
const adminService = services.admin;

function initPage(req, res, callback) {
  getList(req, res, callback);
}

function getList(req, res, callback) {
  const params = req.query;
  const pageId = params.pageId;
  const { WfForm: formModel } = commonService.getModels();
  async.parallel({
    roleList: async.apply(adminService.role.getList, params),
    formList: async.apply(commonService.getList, formModel),
    pageTotal: async.apply(adminService.role.getPageTotal, params),
  }, (error, result) => callback(error, _.assign(result, { pageId })));
}

function saveDetail(req, res, callback) {
  const { SysRole: roleModel } = commonService.getModels();
  const params = req.body;
  params.id = params.id == 0 ? null : params.id;
  if (!_.isEmpty(params.id) && !_.isEmpty(params.deleteIds)) {
    const deleteUserRoleMapping = (next) => {
      const sql = `DELETE FROM elanco_sys.sys_user_role_mapping
                   WHERE NOT(SELECT ARRAY(SELECT (jsonb_array_elements_text(others->'formIds'))::int) && ARRAY[${params.other.formIds}]) 
                         AND id=${params.id};`;
      commonService.executeSql(sql, [], {}, next);
    };
    const getNeedUpdateUserRoleMapping = (next) => {
      const sql = `SELECT * FROM elanco_sys.sys_user_role_mapping WHERE id=${params.id};`;
      commonService.executeSql(sql, [], {}, next);
    };
    const updateUserRoleMapping = (needUpdateMaps, next) => {
      if (!_.isEmpty(needUpdateMaps)) {
        _.forEach(needUpdateMaps, (map) => {
          const currFormIds = (!_.isEmpty(map.others) && !_.isEmpty(map.others.formIds)) ? map.others.formIds : null;
          if (!_.isEmpty(currFormIds)) {
            const intersectionArray = _.intersection(currFormIds, params.deleteIds);
            const diffArray = _.difference(intersectionArray, currFormIds);
            map.others = _.assign(map.others, { formIds: diffArray });
          }
        });
        roleModel.upsert(needUpdateMaps, next);
      } else {
        callback(null, next);
      }
    };
    const saveDetail = (data, next) => {
      roleModel.upsert(params, next);
    };
    async.waterfall([deleteUserRoleMapping, getNeedUpdateUserRoleMapping, updateUserRoleMapping, saveDetail], callback);
  } else {
    const saveDetail = (next) => {
      roleModel.upsert(params, next);
    };
    async.waterfall([saveDetail], callback);
  }
}

function deleteDetail(req, res, callback) {
  const { SysRole: roleModel, SysUserRoleMapping: userRoleMappingModel } = commonService.getModels();
  const id = req.body.id;
  const deleteUserRoleMapping = (next) => {
    userRoleMappingModel.destroyAll({ roleId: id }, error => next(error));
  };
  const deleteDetail = (next) => {
    roleModel.update({ id }, { deleted: true }, next);
  };
  async.waterfall([deleteUserRoleMapping, deleteDetail], callback);
}

module.exports = {
  initPage,
  getList,
  saveDetail,
  deleteDetail,
};
